package SBD.CRUD;

import SBD.Servicios.Conexion;
import SBD.Servicios.FactoriaServicios;
import EP.MetricasContenido.Jaccard;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
* @class JaccardBD
* @author Mauricio Alvarez.
* @brief Realiza las operaciones de CRUD correspondientes a la métrica Jaccard.
*/
public class JaccardBD
{

    //////////////////////
    // OPERACIONES
    //////////////////////

    /**
     * @brief Guarda los resultados de la medición de Jaccard para el body y/o texto alrededor.
     * @param ResultadosJaccard, TopicoConsultado, Umbral, Ranking y OpcionContenido.
     * @return void
    */
    public void GuardarMedicionJaccard(Map<Integer, Jaccard> ResultadosJaccard, 
                                       String TopicoConsultado,
                                       double Umbral,
                                       int Ranking,
                                       int OpcionContenido) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, SQLException
    {

        ////////////////////////////////////////////////////////////////////////
        //PASO 0: Segun la selección de OpcionContenido (1:BODY/2:SURROUND TEXT)
        //        se calcula el tf:
        ////////////////////////////////////////////////////////////////////////

        Conexion cdb = FactoriaServicios.getInstancia().getConexionBD();

        ////////////
        // BODY   //
        ////////////
        if (OpcionContenido == 1)
        {

            ////////////////////////////////////////////////////////////////////////
            //PASO 1: Se guardan los parametros de la medición en la tabla Jaccard:
            ////////////////////////////////////////////////////////////////////////
            cdb.un_sql = "INSERT INTO JACCARD(termino, umbral) VALUES ('" + TopicoConsultado + "','" + Umbral +"');";
            cdb.un_st.executeUpdate(cdb.un_sql);

            //////////////////////////////////////////////////////
            //PASO 2: El ultimo registro ingresado a la Tabla:
            //////////////////////////////////////////////////////
            cdb.un_sql = "SELECT id_jaccard FROM JACCARD ORDER BY id_jaccard DESC LIMIT 1";
            cdb.resultado = cdb.un_st.executeQuery(cdb.un_sql);
            if (cdb.resultado != null)
            {
                if (cdb.resultado.next())
                {
                    int id_jaccard = cdb.resultado.getInt("id_jaccard");

                    //////////////////////////////////////////////////////////////////////////////////
                    //PASO 3: Se guardan los resultados de la medición en la tabla MEDICION_JACCARD:
                    //////////////////////////////////////////////////////////////////////////////////
                    Set set = ResultadosJaccard.entrySet();
                    Iterator i = set.iterator();

                    while(i.hasNext())
                    {
                        Map.Entry me = (Map.Entry)i.next();
                        Jaccard jaccard = new Jaccard();
                        jaccard =  (Jaccard) me.getValue();

                        int id_pagina = jaccard.getId_pagina();
                        double coeficiente_j = jaccard.getCoeficienteJaccard();
                        double distancia_j = jaccard.getDistanciaJaccard();

                        cdb.un_sql = "INSERT INTO MEDICION_JACCARD(id_jaccard, id_pagina, coeficiente_j, distancia_j) VALUES ('" + id_jaccard + "','" + id_pagina + "'," + coeficiente_j + "," + distancia_j + ")";
                        cdb.un_st.executeUpdate(cdb.un_sql);

                    }
                }
            }

        }//FIN IF BODY



        ////////////////////
        // SURROUND TEXT  //
        ////////////////////

        if (OpcionContenido == 2)
        {

            ////////////////////////////////////////////////////////////////////////
            //PASO 1: Se guardan los parametros de la medición en la tabla Jaccard:
            ////////////////////////////////////////////////////////////////////////
            cdb.un_sql = "INSERT INTO JACCARD_ST (termino, umbral) VALUES ('" + TopicoConsultado + "','" + Umbral +"');";
            cdb.un_st.executeUpdate(cdb.un_sql);

            //////////////////////////////////////////////////////
            //PASO 2: El ultimo registro ingresado a la Tabla:
            //////////////////////////////////////////////////////
            cdb.un_sql = "SELECT id_jaccard_st FROM JACCARD_ST ORDER BY id_jaccard_st DESC LIMIT 1";
            cdb.resultado = cdb.un_st.executeQuery(cdb.un_sql);
            if (cdb.resultado != null)
            {
                if (cdb.resultado.next())
                {
                    int id_jaccard_st = cdb.resultado.getInt("id_jaccard_st");

                    ////////////////////////////////////////////////////////////////////////////////////////
                    //PASO 3: Se guardan los resultados de la medición en la tabla MEDICION_JACCARD_ST:
                    ////////////////////////////////////////////////////////////////////////////////////////
                    Set set = ResultadosJaccard.entrySet();
                    Iterator i = set.iterator();

                    while(i.hasNext())
                    {
                        Map.Entry me = (Map.Entry)i.next();
                        Jaccard jaccard = new Jaccard();
                        jaccard =  (Jaccard) me.getValue();

                        int id_relacion_pag = jaccard.getId_relacion_pag();
                        double coeficiente_j = jaccard.getCoeficienteJaccard();
                        double distancia_j = jaccard.getDistanciaJaccard();

                        cdb.un_sql = "INSERT INTO MEDICION_JACCARD_ST (id_relacion_pag, id_jaccard_st, coeficiente_j, distancia_j) VALUES ('" + id_relacion_pag + "','" + id_jaccard_st + "'," + coeficiente_j + "," + distancia_j + ")";
                        cdb.un_st.executeUpdate(cdb.un_sql);
                        
                        //Mejora (04-oct-2011): Se inserta pje. Jaccard en tabla "relación pagina".
                        cdb.un_sql = "UPDATE RELACION_PAGINAS SET PJE_PREDICTOR_JACCARD = '" + coeficiente_j + "' WHERE id_relacion_pag = '" + id_relacion_pag +"';";
                        cdb.un_st.executeUpdate(cdb.un_sql);                        

                    }

                }
            }
        }//FIN IF SURROUND TEXT


    }//FIN GuardarMedicionJaccard


    /**
     * @brief Rankea los resultados obtenidos por la medición euclidiana para las páginas y/o el texto alrededor.
     * @param Cantidad en el Ranking y la Consulta .
     * @return void
    */
    public void RankearMedicionJaccard(int Ranking, String TopicoConsultado, int OpcionContenido) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, SQLException
    {

        ////////////////////////////////////////////////////////////////////////
        //PASO 0: Segun la selección de OpcionContenido (1:BODY/2:SURROUND TEXT)
        //        se calcula el tf:
        ////////////////////////////////////////////////////////////////////////

        Conexion cdb = FactoriaServicios.getInstancia().getConexionBD();

        ////////////
        // BODY   //
        ////////////
        if (OpcionContenido == 1)
        {

            ////////////////////////////////////////////////////////
            //PASO 1: Se cargan las páginas segun ranking y umbral
            ////////////////////////////////////////////////////////

            int ranking_j  = 1;
            int contador = 0;
            HashMap<Integer,Integer> RankingPagina = new HashMap<Integer,Integer>();

            cdb.un_sql = "SELECT * FROM MEDICION_JACCARD ORDER BY coeficiente_j DESC";
            cdb.resultado = cdb.un_st.executeQuery(cdb.un_sql);
            if (cdb.resultado != null)
            {

                while (cdb.resultado.next())
                {
                    try {

                       int id_mjaccard = cdb.resultado.getInt("id_mjaccard");
                       int id_jaccard = cdb.resultado.getInt("id_jaccard");
                       int id_pagina = cdb.resultado.getInt("id_pagina");
                       double coeficiente_j = cdb.resultado.getDouble("coeficiente_j");
                       double distancia_j = cdb.resultado.getDouble("distancia_j");


                       //Se escriben en el archivo de texto solo las k-mejores paginas pedidas por el usuario:
                       if (contador < Ranking)
                       {
                          contador++;
                       }

                       RankingPagina.put(id_mjaccard, ranking_j);
                       ranking_j++;

                    } catch (Exception e) {
                        System.out.println("ERROR: No se ha podido crear archivo Ranking Jaccard.");
                    }

                }

            }

            // Se Actualiza el raking:
            ActualizarRanking(RankingPagina, OpcionContenido);


        }//FIN IF BODY



        ////////////////////
        // SURROUND TEXT  //
        ////////////////////

        if (OpcionContenido == 2)
        {

            ////////////////////////////////////////////////////////
            //PASO 1: Se cargan las páginas segun ranking y umbral
            ////////////////////////////////////////////////////////

            int ranking_j  = 1;
            int contador = 0;
            Map<Integer,Integer> RankingST = new HashMap();

            cdb.un_sql = "SELECT rp.ID_RELACION_PAG, p2.URL AS ORIGEN, p.URL AS DESTINO, mjst.ID_MJACCARD_ST, mjst.ID_RELACION_PAG, mjst.ID_JACCARD_ST, mjst.COEFICIENTE_J, mjst.DISTANCIA_J, mjst.RANKING_J"+
                         " FROM relacion_paginas AS rp"+
                         " INNER JOIN pagina AS p"+
                         " ON rp.ID_PAGINA_DESTINO = p.ID_PAGINA"+
                         " INNER JOIN pagina AS p2"+
                         " ON rp.ID_PAGINA_FUENTE = p2.ID_PAGINA"+
                         " INNER JOIN medicion_jaccard_st AS mjst"+
                         " ON mjst.ID_RELACION_PAG = rp.ID_RELACION_PAG"+
                         " ORDER BY mjst.COEFICIENTE_J DESC";

            cdb.resultado = cdb.un_st.executeQuery(cdb.un_sql);
            if (cdb.resultado != null)
            {

                while (cdb.resultado.next())
                {
                    try {

                       int id_mjaccard_st = cdb.resultado.getInt("id_mjaccard_st");
                       int id_relacion_pag = cdb.resultado.getInt("id_relacion_pag");
                       int id_jaccard_st = cdb.resultado.getInt("id_jaccard_st");
                       String pag_origen = cdb.resultado.getString("ORIGEN");
                       String pag_destino =  cdb.resultado.getString("DESTINO");
                       double coeficiente_j = cdb.resultado.getDouble("coeficiente_j");
                       double distancia_j = cdb.resultado.getDouble("distancia_j");


                       //Se escriben en el archivo de texto solo las k-mejores paginas pedidas por el usuario:
                       if (contador < Ranking)
                       {
                          contador++;
                       }

                       RankingST.put(id_mjaccard_st, ranking_j);
                       ranking_j++;

                    } catch (Exception e) {
                        System.out.println("ERROR: No se ha podido crear archivo Ranking Jaccard ST.");
                    }

                }

            }

            // Se Actualiza el raking:
            ActualizarRanking(RankingST, OpcionContenido);

        }//FIN IF SURROUND TEXT


    }//FIN RankearMedicionJaccard

    

    public void ActualizarRanking (Map RankingPagina, int OpcionContenido) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException, IOException
    {

        ////////////////////////////////////////////////////////////////////////
        //PASO 0: Segun la selección de OpcionContenido (1:BODY/2:SURROUND TEXT)
        //        se calcula el tf:
        ////////////////////////////////////////////////////////////////////////

        Conexion cdb = FactoriaServicios.getInstancia().getConexionBD();

        ////////////
        // BODY   //
        ////////////
        if (OpcionContenido == 1)
        {
            Set set = RankingPagina.entrySet();
            Iterator i = set.iterator();

            while(i.hasNext())
            {
                Map.Entry me = (Map.Entry)i.next();
                cdb.un_sql = "UPDATE MEDICION_JACCARD SET ranking_j = '" + me.getValue() + "' WHERE id_mjaccard = '" + me.getKey() +"';";
                cdb.un_st.executeUpdate(cdb.un_sql);
            }
        }//FIN IF BODY


        ////////////////////
        // SURROUND TEXT  //
        ////////////////////

        if (OpcionContenido == 2)
        {
            Set set = RankingPagina.entrySet();
            Iterator i = set.iterator();

            while(i.hasNext())
            {
                Map.Entry me = (Map.Entry)i.next();
                cdb.un_sql = "UPDATE MEDICION_JACCARD_ST SET ranking_j = '" + me.getValue() + "' WHERE id_mjaccard_st = '" + me.getKey() +"';";
                cdb.un_st.executeUpdate(cdb.un_sql);
            }
        }//FIN IF SURROUND TEXT


    }//FIN ActualizarRanking

}//FIN CLASE JaccardBD